package com.hrt.datasender.web.monitordata;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import com.btcode.exception.MsgException;
import com.btcode.orm.model.IModel;
import com.hrt.datasender.datadao.model.BcSendPlatformDataStrategyModel;
import com.hrt.datasender.datadao.model.BcSendPlatformModel;
import com.hrt.datasender.datadao.service.BcSendPlatformDataStrategyService;
import com.hrt.datasender.datadao.service.BcSendPlatformService;
import com.hrt.datasender.mq.MqKit;
import com.hrt.datasender.mq.model.PacketModel;
import com.hrt.datasender.process.strategy.IProcessStrategy;
import com.hrt.datasender.process.strategy.ProcessStrategyLoader;
import org.springframework.stereotype.Service;

import com.btcode.common.MyLog;
import com.btcode.db.result.DataHelper;
import com.btcode.db.result.Row;
import com.btcode.log.ILog;
import com.hrt.datasender.datastorage.strategy.IStorageStrategy;
import com.hrt.datasender.datastorage.strategy.StrategyLoader;
import com.hrt.datasender.datastorage.strategy.monitordata.MonitorDataStrategy;
import com.hrt.db.DBManager;

@Service
public final class MonitorDataService {

    private static volatile MonitorDataService instance;

    private ILog log;

    private MonitorDataService() {
        log = MyLog.getInstance().getLogger(getClass());
    }

    public static MonitorDataService getInstance() {
        if (instance == null) {
            synchronized (MonitorDataService.class) {
                if (instance == null) {
                    instance = new MonitorDataService();
                }
            }
        }
        return instance;
    }

    public MonitorDataModel getMonitorData(Map<String, String> params) throws ParseException, Exception {
        String[] outputFields = new String[] { "MEAS_RE", "MEAS_ZS" };

        String strategyId = params.get("strategyId");
        IStorageStrategy strategy = StrategyLoader.getInstance().getStrategyById(strategyId);

        MonitorDataStrategy mdStrategy = (MonitorDataStrategy) strategy;

        MonitorDataModel result = getHistoryDataCommom(params, mdStrategy, outputFields);
        return result;
    }

    public MonitorDataModel getSourceSingleData() throws ParseException {

        String[] outputFields = new String[] { "MEAS_RE", "MEAS_ZS" };

        String sql = " SELECT * FROM BD_SOURCE_SINGLE ";
        List<Row> rows = DBManager.getDataExecuter().queryList(sql, null);

        List<String> rowToColFields = new ArrayList<String>();
        for (String field : outputFields) {
            rowToColFields.add(field);
        }

        rows = DataHelper.RowToCol(rows, "DATATIME", rowToColFields, "PARAM_CODE_BUS");

        MonitorDataModel monitorModel = new MonitorDataModel();
        monitorModel.setData(rows);

        return monitorModel;
    }

    /**
     * 通用的获取历史数据方法 实时，分钟，小时，周期，和天都可以共用，报表除外
     * 
     * @param params
     *            查询参数：MN,START,END,waterType
     * @param tableName
     *            要查询的表名
     * @param dataField
     *            要查询的数据字段，实时数据为RTD，其他为AVG，同时也作为行转列的依据
     * @return 返回的结果会进行行转列，同一个时间，不同参数的回合并成一行 并进行小数位格式化，添加报警信息
     * @throws ParseException
     */
    private MonitorDataModel getHistoryDataCommom(Map<String, String> params, MonitorDataStrategy strategy,
            String[] dataFields) throws ParseException {

        String start = params.get("START");
        String end = params.get("END");

        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Date startDate = sf.parse(start);
        Date endDate = sf.parse(end);

        log.info("查询监测数据，【策略名称】：" + strategy.getShowName() + ",【策略ID】：" + strategy.getStrategyId() + "【策略table】:"
                + strategy.getStoageTable());

        MonitorDataModel result = MonitorDataUtil.getInstance().getHistoryData(startDate, endDate,
                strategy.getStoageTable(), dataFields);
        result = processHistoryData(result, dataFields, strategy, startDate, endDate);

        return result;
    }

    /**
     * 二次加工历史数据 行转列 小数点格式化 增加报警信息 数据缺失留白 gislin 2017年4月26日
     * 
     * @param monitorDataModel
     *            待处理的数据
     * @param waterType
     *            业务类型，区分地表水，污水工业污染源
     * @param mn
     *            站点mn号
     * @param parms
     *            要处理的污染物code数组
     * @param dataFields
     *            要查的数据字段数组，比如AVG,COU,RTD等
     * @param dataType
     * @param startDate
     * @param endDate
     * @return
     */
    public MonitorDataModel processHistoryData(MonitorDataModel monitorDataModel, String[] dataFields,
            MonitorDataStrategy strategy, Date startDate, Date endDate) {

        long startTime = System.currentTimeMillis(); // 获取开始时间
        long endTime = System.currentTimeMillis(); // 获取结束时间

        List<String> rowToColFields = new ArrayList<String>();
        for (String field : dataFields) {
            rowToColFields.add(field);
        }
        rowToColFields.add("FLAG");

        startTime = System.currentTimeMillis();
        monitorDataModel
                .setData(DataHelper.RowToCol(monitorDataModel.getData(), "DATATIME", rowToColFields, "PARAM_CODE_BUS"));
        endTime = System.currentTimeMillis();
        System.out.println("行转列时间： " + (endTime - startTime) + "ms");

        startTime = System.currentTimeMillis();
        monitorDataModel.setData(
                MonitorDataUtil.getInstance().fixMissData(monitorDataModel.getData(), strategy, startDate, endDate));
        endTime = System.currentTimeMillis();
        System.out.println("数据缺失补全： " + (endTime - startTime) + "ms");

        startTime = System.currentTimeMillis();
        monitorDataModel = MonitorDataFormater.getInstance().numPointFormat(monitorDataModel);
        endTime = System.currentTimeMillis();
        System.out.println("小数点格式化： " + (endTime - startTime) + "ms");

        return monitorDataModel;
    }

    /**
     * 补传数据
     * @param params
     * @return
     * @throws Exception
     */
    public List<PacketModel> reissueMinitorData(Map<String, String> params) throws Exception {
        List<PacketModel> models = new ArrayList<>();
        String start = params.get("START");
        String end = params.get("END");
        String platFormID = params.get("PLATFORM_ID");
        String storageStrategyId = params.get("strategyId");

        BcSendPlatformModel platform = new BcSendPlatformModel();
        platform.setPlatformId(platFormID);
        platform = BcSendPlatformService.getInstance().getModel(platform);
        String ip = platform.getIp();
        String port = platform.getPort();
        String mn = platform.getMn();
        if (mn == null || mn.equals("")) {
            throw new MsgException("平台：" + platform.getName() + "没有mn号");
        }

        BcSendPlatformDataStrategyModel dataStrategyModel = new BcSendPlatformDataStrategyModel();
        dataStrategyModel.setPlatformId(platFormID);
        dataStrategyModel.setStorageStrategyId(storageStrategyId);
        List<BcSendPlatformDataStrategyModel> dataStrategyModels = BcSendPlatformDataStrategyService.getInstance().
                getModels(dataStrategyModel);
        if(dataStrategyModels!=null&&dataStrategyModels.size()>0){
            dataStrategyModel = dataStrategyModels.get(0);
        }
        else{
            throw new MsgException("平台：" + platform.getName() + "没有对应的数据策略");
        }

        String processStrategyId = dataStrategyModel.getProcessStrategyId();
        IStorageStrategy strategy = StrategyLoader.getInstance().getStrategyById(storageStrategyId);
        MonitorDataStrategy mdStrategy = (MonitorDataStrategy) strategy;

        //根据开始时间与结束时间,获取补传数据时间
        SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date startDate = sdf.parse(start);
        Date endDate = sdf.parse(end);
        long startTime  = startDate.getTime();
        long endTime  = endDate.getTime();
        long timeInterval = (long)mdStrategy.getDataInterval() * 1000;

        while(startTime < endTime){
            List<Row> sendData = mdStrategy.getData(platform,startTime);
            if (sendData == null || sendData.size() <= 0) {
                startTime += timeInterval;
                continue;
            }

            IProcessStrategy processStrategy = ProcessStrategyLoader.getInstance().getStrategyById(platFormID,
                    processStrategyId);
            Object msg = processStrategy.packetReissue(sendData, platform);
            PacketModel packetModel = new PacketModel();
            packetModel.setIp(ip);
            packetModel.setPort(port);
            packetModel.setMn(mn);
            packetModel.setMsg(msg);

            MqKit.productMsgToReissueDataMQ(packetModel);
            models.add(packetModel);
            startTime += timeInterval;
        }
        return models;
    }

    /**
     * 补生成数据
     * @param params
     * @throws Exception
     */
    public void generateMinitorData(Map<String, String> params) throws Exception {
        String dataTime = params.get("DATATIME");
        String parm = params.get("PARMLIST");
        List<String> parmList = Arrays.asList(parm.split(","));
        String storageStrategyId = params.get("strategyId");
        SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date =sdf.parse(dataTime);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);

        IStorageStrategy strategy = StrategyLoader.getInstance().getStrategyById(storageStrategyId);
        MonitorDataStrategy mdStrategy = (MonitorDataStrategy) strategy;
        cal.add(Calendar.MINUTE,mdStrategy.getDataInterval()/60);

        List<IModel> models = mdStrategy.getStorageData(cal,parmList);
        if(models != null && models.size()>0){
            DBManager.getORMExecuter().creates(models);

        }else{
            throw new MsgException("补生成统计数据失败，库里无基础数据");
        }
    }

}
